package com.inspector.app.di.util

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.res.Resources
import android.graphics.Color
import android.graphics.Rect
import android.os.Build
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowInsets
import android.view.WindowManager
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import com.google.android.material.snackbar.Snackbar
import com.google.gson.Gson
import com.google.gson.JsonElement
import com.google.gson.reflect.TypeToken
import com.inspector.app.R
import org.greenrobot.eventbus.EventBus
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date


object UI {

    fun Activity.makeStatusBarTransparent(isLight: Boolean) {
        try {
            //https://developer.android.com/develop/ui/views/layout/edge-to-edge-manually?hl=zh-cn#change-color
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                WindowCompat.setDecorFitsSystemWindows(window, false)
//                val windowInsetsController = ViewCompat.getWindowInsetsController(window.decorView)
                val windowInsetsController =
                    WindowCompat.getInsetsController(window, window.decorView)
                windowInsetsController.isAppearanceLightStatusBars = isLight
                windowInsetsController.isAppearanceLightNavigationBars = isLight
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { //android Q+ 去掉虚拟导航键 的灰色半透明遮罩
                    window.isNavigationBarContrastEnforced = false
                }
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //设置虚拟导航键的 背景色为透明 8.0+ 虚拟导航键图标颜色可以修改，所以背景可以用透明
                    window.navigationBarColor = Color.TRANSPARENT
                } else {  //低版本因为导航键图标颜色无法修改，建议用黑色，不要透明
                    window.navigationBarColor = Color.BLACK
                }
                return
            }
            window.apply {
                clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
                addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
                if (isLight) { //[黑色字体]
                    decorView.systemUiVisibility =
                        View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                } else { //[白色字体]
                    decorView.systemUiVisibility =
                        View.SYSTEM_UI_FLAG_VISIBLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                }
                statusBarColor = Color.TRANSPARENT
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun registerEvents(subscriber: Any) {
        val registered = EventBus.getDefault().isRegistered(subscriber)
        if (!registered) {
            EventBus.getDefault().register(subscriber)
        }
    }

    fun unregisterEvents(subscriber: Any) {
        val registered = EventBus.getDefault().isRegistered(subscriber)
        if (registered) {
            EventBus.getDefault().unregister(subscriber)
        }
    }

    fun View.setMarginTop(marginTop: Int) {
        val menuLayoutParams = this.layoutParams as ViewGroup.MarginLayoutParams
        menuLayoutParams.setMargins(0, marginTop, 0, 0)
        this.layoutParams = menuLayoutParams
    }

    fun getStatusBarHeight(activity: Activity): Int {
        try {
            val resourceId =
                activity.resources.getIdentifier("status_bar_height", "dimen", "android")
            if (resourceId > 0) {
                val statusBarHeight = activity.resources.getDimensionPixelSize(resourceId)
                return statusBarHeight
            }
            // fall back ...
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                val windowInsets = activity.window.decorView.rootWindowInsets
                return windowInsets.getInsets(WindowInsets.Type.statusBars()).top
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                val windowInsets = activity.window.decorView.rootWindowInsets
                if (windowInsets != null) {
                    val displayCutout = windowInsets.displayCutout
                    if (displayCutout != null) {
                        return displayCutout.safeInsetTop
                    }
                }
                return 0
            } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val decorView = activity.window.decorView
                val insets = decorView.rootWindowInsets
                if (insets != null) {
                    return insets.systemWindowInsetTop
                }
                return 0
            } else {
                val rectangle: Rect = Rect()
                val window = activity.window
                window.decorView.getWindowVisibleDisplayFrame(rectangle)
                return rectangle.top
            }
        } catch (e: Exception) {
            return dipToPx(25f)
        }
    }

    fun dpToPx(dp: Int): Int {
        return (dp * Resources.getSystem().displayMetrics.density).toInt()
    }

    fun dipToPx(dp: Float): Int {
        return (dp * Resources.getSystem().displayMetrics.density).toInt()
    }

    fun pxToDp(px: Int): Int {
        return (px / Resources.getSystem().displayMetrics.density).toInt()
    }


    fun displayTopSnackBar(activity: Activity, view: View, message: String) {
        val snackbar = Snackbar.make(view, message, Snackbar.LENGTH_LONG)
        snackbar.setBackgroundTint(ContextCompat.getColor(view.context, R.color.nav_color))
        val snackBarView = snackbar.view
        val params = snackBarView.layoutParams
        val margin = UI.dpToPx(12)
        if (params is CoordinatorLayout.LayoutParams) {
            params.gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
            params.setMargins(margin, getStatusBarHeight(activity) + margin, margin, 0)
        } else {
            (params as FrameLayout.LayoutParams).gravity = Gravity.TOP or Gravity.CENTER_HORIZONTAL
            params.setMargins(margin, getStatusBarHeight(activity) + margin, margin, 0)
        }
        snackBarView.layoutParams = params
        snackbar.show()
    }


    fun formatDate(pattern: String) {
        formatDate(Date(), pattern)
    }

    fun formatDate(date: Date, pattern: String): String {
        val format = SimpleDateFormat(pattern)
        return format.format(date).trim()
    }

    @SuppressLint("SimpleDateFormat")
    fun formatStringDate(dateString: String?, pattern: String, outputPattern: String): String {
        return try {
            if (dateString.isNullOrEmpty()) return "--"
            val date = SimpleDateFormat(pattern).parse(dateString)
            return date?.let { SimpleDateFormat(outputPattern).format(it) } ?: "--"
        } catch (e: Exception) {
            "--"
        }
    }


    fun addOneDayToDate(date: Date): Date {
        val calendar = Calendar.getInstance()
        calendar.time = date
        calendar.add(Calendar.DAY_OF_MONTH, 1)
        return calendar.time
    }


}


fun ViewGroup.inflate(layoutRes: Int): View {
    return LayoutInflater.from(context).inflate(layoutRes, this, false)
}

inline fun <reified T> fromJson(jsonString: JsonElement?): T? {
    return try {
        Gson().fromJson<T>(jsonString, object : TypeToken<T>() {}.type)
    } catch (e: Exception) {
        e.printStackTrace()
        null
    }
}

fun <T> LiveData<T>.observeOnce(owner: LifecycleOwner, reactToChange: (T) -> Unit): Observer<T> {
    val wrappedObserver = object : Observer<T> {
        override fun onChanged(data: T) {
            reactToChange(data)
            removeObserver(this)
        }
    }

    observe(owner, wrappedObserver)
    return wrappedObserver
}